package tr.edu.metu.is.mega.client.course.activity;

import java.util.ArrayList;
import java.util.List;

import tr.edu.metu.is.mega.client.core.DialogCallbackAdapter;
import tr.edu.metu.is.mega.client.core.MegaUtil;
import tr.edu.metu.is.mega.client.core.event.SelectionEventBus;
import tr.edu.metu.is.mega.client.course.CourseChangeEvent;
import tr.edu.metu.is.mega.client.resource.MEGAIconBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResourceBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResources;
import tr.edu.metu.is.mega.client.schedule.ScheduleTemplateSelectDialog;
import tr.edu.metu.is.mega.client.schedule.ScheduleTemplateTransformHelper;
import tr.edu.metu.is.mega.client.service.GwtCourseService;
import tr.edu.metu.is.mega.client.service.GwtCourseServiceAsync;
import tr.edu.metu.is.mega.common.dto.ActivityDTO;
import tr.edu.metu.is.mega.common.dto.CourseDTO;
import tr.edu.metu.is.mega.common.dto.ScheduleTemplateDTO;

import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelFactory;
import com.extjs.gxt.ui.client.data.BeanModelLookup;
import com.extjs.gxt.ui.client.dnd.GridDragSource;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.WindowEvent;
import com.extjs.gxt.ui.client.event.WindowListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.DateField;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.CenterLayout;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 * Container to manage course activities
 */
public class ScheduleManagementDialog extends Window {

    private MEGAResourceBundle resourceBundle;

    private MEGAIconBundle iconBundle;

    private Grid<BeanModel> grid;

    private BeanModelFactory beanModelFactory;

    private final CourseDTO course;

    /**
     * Default constructor.
     * 
     * @param course
     */
    public ScheduleManagementDialog(CourseDTO course) {
        this.course = course;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onRender(Element parent, int pos) {
        super.onRender(parent, pos);
        resourceBundle = MEGAResources.RESOURCEBUNDLE;
        iconBundle = MEGAResources.ICONBUNDLE;
        beanModelFactory = BeanModelLookup.get().getFactory(ActivityDTO.class);
        setHeading(resourceBundle.activityTemplateHeading());
        setSize(500, 500);
        setLayout(new FitLayout());
        setModal(true);
        ContentPanel panel = new ContentPanel();
        panel.setHeaderVisible(false);
        panel.setLayout(new FitLayout());

        panel.add(getGrid());
        panel.setTopComponent(getToolBar());
        add(panel);

        Button saveButton = new Button("Save");
        saveButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                hide();
                course.setActivities(getActivities());
                getService().updateCourse(course, new AsyncCallback<CourseDTO>() {

                    @Override
                    public void onSuccess(CourseDTO result) {
                        SelectionEventBus.getInstance().fireEvent(CourseChangeEvent.UPDATE, result);
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                    }
                });
            }
        });
        panel.addButton(saveButton);

        Button cancelButton = new Button("Cancel");
        cancelButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                hide();
            }
        });
        panel.addButton(cancelButton);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void afterRender() {
        super.afterRender();
        if (course != null && course.getActivities() != null) {
            setActivities(course.getActivities());
        }
    }

    /**
     * Initializes and returns toolbar.
     * 
     * @return toolbar
     */
    private ToolBar getToolBar() {
        ToolBar toolBar = new ToolBar();
        toolBar.setMinButtonWidth(70);
        toolBar.setSpacing(5);

        Button addButton = new Button(resourceBundle.add(), AbstractImagePrototype.create(iconBundle.add()));
        addButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                ActivityEditDialog dialog = new ActivityEditDialog();
                ActivityDTO dto = new ActivityDTO();
                dialog.create(dto, new DialogCallbackAdapter<ActivityDTO>() {

                    @Override
                    public void onOk(ActivityDTO param) {
                        grid.getStore().add(beanModelFactory.createModel(param));
                    }
                });

            }
        });

        Button updateButton = new Button(resourceBundle.update(), AbstractImagePrototype.create(iconBundle.update()));
        updateButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (grid.getSelectionModel().getSelectedItem() != null) {
                    ActivityEditDialog dialog = new ActivityEditDialog();
                    ActivityDTO dto = grid.getSelectionModel().getSelectedItem().getBean();
                    dialog.update(dto, new DialogCallbackAdapter<ActivityDTO>() {

                        @Override
                        public void onOk(ActivityDTO param) {
                            grid.getStore().update(beanModelFactory.createModel(param));
                        }
                    });
                }

            }
        });

        Button deleteButton = new Button(resourceBundle.delete(), AbstractImagePrototype.create(iconBundle.delete()));
        deleteButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (grid.getSelectionModel().getSelectedItem() != null) {
                    grid.getStore().remove(grid.getSelectionModel().getSelectedItem());
                }
            }
        });
        Button pullFromTemplateButton = new Button(resourceBundle.pullFromTemplate(), AbstractImagePrototype.create(iconBundle.importInto()));
        pullFromTemplateButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                ScheduleTemplateSelectDialog dialog = new ScheduleTemplateSelectDialog(false, false);
                dialog.select(new DialogCallbackAdapter<ScheduleTemplateDTO>() {

                    @Override
                    public void onOk(final ScheduleTemplateDTO param) {
                        Dialog dialog = new Dialog();
                        final DateField dateField = new DateField();
                        dialog.setHeading("Choose first day of semester");
                        dialog.setLayout(new CenterLayout());
                        dialog.add(dateField);
                        dialog.setModal(true);
                        dialog.setHideOnButtonClick(true);
                        dialog.addWindowListener(new WindowListener() {

                            @Override
                            public void windowHide(WindowEvent we) {
                                if (dateField.getValue() != null) {
                                    super.windowHide(we);
                                    setActivities(ScheduleTemplateTransformHelper.transform(param.getActivities(), dateField.getValue()));
                                } else {
                                    MessageBox.alert("Choose Date", "Choose date", null);
                                }
                            }
                        });
                        dialog.show();
                    }
                });

            }
        });

        toolBar.add(addButton);
        toolBar.add(updateButton);
        toolBar.add(deleteButton);
        toolBar.add(pullFromTemplateButton);

        return toolBar;
    }

    /**
     * Returns activity grid.
     * 
     * @return grid
     */
    private Grid<BeanModel> getGrid() {
        if (grid == null) {

            ListStore<BeanModel> store = new ListStore<BeanModel>();
            List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
            columns.add(new ColumnConfig(ActivityDTO.FIELD_TYPE, resourceBundle.activityTemplateType(), 150));
            ColumnConfig columnConfig = new ColumnConfig(ActivityDTO.FIELD_DUEDATE, resourceBundle.activityTemplateDueDate(), 150);
            columnConfig.setRenderer(MegaUtil.getDateRenderer(MegaUtil.LONG_DATE_STYLE));
            columns.add(columnConfig);
            columnConfig = new ColumnConfig(ActivityDTO.FIELD_ALERT_TIME, resourceBundle.activityTemplateAlertTime(), 150);
            columns.add(columnConfig);
            columnConfig.setRenderer(MegaUtil.getDateRenderer(MegaUtil.LONG_DATE_STYLE));
            columns.add(new ColumnConfig(ActivityDTO.FIELD_DESCRIPTION, resourceBundle.activityTemplateDescription(), 150));

            ColumnModel cm = new ColumnModel(columns);

            grid = new Grid<BeanModel>(store, cm);

            new GridDragSource(grid);

            MegaUtil.decoradeGridViewWithAutoHeight(grid, true);

        }
        return grid;
    }

    /**
     * Adds activities to grid
     * 
     * @param activityList
     */
    public void setActivities(List<ActivityDTO> activityList) {
        grid.getStore().removeAll();
        for (ActivityDTO activity : activityList) {
            grid.getStore().add(beanModelFactory.createModel(activity));
        }
    }

    /**
     * Gets activities from grid.
     * 
     * @return list of activities
     */
    public List<ActivityDTO> getActivities() {
        List<ActivityDTO> activities = new ArrayList<ActivityDTO>(grid.getStore().getModels().size());
        for (BeanModel model : grid.getStore().getModels()) {
            ActivityDTO activity = (ActivityDTO) model.getBean();
            activities.add(activity);
        }
        return activities;
    }

    public static GwtCourseServiceAsync getService() {
        return GwtCourseService.Util.getInstance();
    }

}
